package com.ruoyi.hyperledge.chaincode;

import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.ruoyi.hyperledge.dto.FileDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.StringUtils;
import com.ruoyi.hyperledge.config.HyperLedgerFabricProperties;
import com.ruoyi.hyperledge.dto.DataDTO;
import org.hyperledger.fabric.client.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class Invokecode {


    final Gateway gateway;

    final Contract contract;

    final HyperLedgerFabricProperties hyperLedgerFabricProperties;

    @Autowired
    public Invokecode(Gateway gateway, Contract contract, HyperLedgerFabricProperties hyperLedgerFabricProperties) {
        this.gateway = gateway;
        this.contract = contract;
        this.hyperLedgerFabricProperties = hyperLedgerFabricProperties;
    }

    //创建数据
    public Map<String, Object> createData(DataDTO dataDTO) throws Exception {
        Map<String, Object> result = Maps.newConcurrentMap();
        Map<String, List<FileDTO>> stages = dataDTO.getStages();
        Gson gson = new Gson();
        String stagesJson = gson.toJson(stages);
//        System.out.println(stagesJson);
        byte[] bytes = contract.submitTransaction("createData",
                dataDTO.getDataName(),
                dataDTO.getStandardCode(),
                dataDTO.getRemark(),
                stagesJson);
        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");
        return result;
    }

    //更改数据
    public Map<String, Object> updateData(String dataName,
                                          String stage, String oldFileName, FileDTO newfile) throws Exception {
        try {
            Map<String, Object> result = Maps.newConcurrentMap();
            byte[] bytes = contract.submitTransaction("updateData",
                    dataName,
                    stage,
                    oldFileName,
                    newfile.getFileName(),
                    newfile.getFilePath(),
                    newfile.getOperUser(),
                    newfile.getOperTime());
            log.info("提交成功 ");
            result.put("payload", StringUtils.newStringUtf8(bytes));
            result.put("status", "ok");
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Map<String, Object> queryData(String key) throws Exception {

        Map<String, Object> result = Maps.newConcurrentMap();
        byte[] data = contract.evaluateTransaction("queryData", key);

        result.put("payload", StringUtils.newStringUtf8(data));
        result.put("status", "ok");

        return result;
    }

    public Map<String, Object> deleteData(String key) throws Exception {
        Map<String, Object> result = Maps.newConcurrentMap();
        byte[] data = contract.submitTransaction("deleteData", key);

        result.put("payload", StringUtils.newStringUtf8(data));
        result.put("status", "ok");

        return result;
    }

    //获取最后一次删除后的新建数据
    public List<DataDTO> queryCurrentHistory(String key) throws Exception {


        byte[] dataHistory = contract.evaluateTransaction("queryCurrentHistory",key);

        String result = StringUtils.newStringUtf8(dataHistory);

        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(result, JsonObject.class);


        JsonArray dataHistoriesArray = jsonObject.getAsJsonArray("dataHistories");


        List<DataDTO> dataDTOList = new ArrayList<>();


        for (int i = 0; i < dataHistoriesArray.size(); i++) {
            JsonObject oneData = dataHistoriesArray.get(i).getAsJsonObject();


            DataDTO dataDTO = new DataDTO();
            dataDTO.setDataName(oneData.get("dataName").getAsString());
            dataDTO.setStandardCode(oneData.get("standardCode").getAsString());
            dataDTO.setRemark(oneData.get("remark").getAsString());
            dataDTO.setStages(gson.fromJson(oneData.get("stages"), new TypeToken<Map<String, List<FileDTO>>>() {
            }.getType()));


            dataDTOList.add(dataDTO);
        }


        return dataDTOList;
    }

    //获取该数据名称下的所有数据
    public List<DataDTO> queryHistory(String key) throws Exception {


        byte[] dataHistory = contract.evaluateTransaction("queryOneDataHistory", key);

        String result = StringUtils.newStringUtf8(dataHistory);
        System.out.println(result);
        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(result, JsonObject.class);


        JsonArray dataHistoriesArray = jsonObject.getAsJsonArray("dataHistories");


        List<DataDTO> dataDTOList = new ArrayList<>();


        for (int i = 0; i < dataHistoriesArray.size(); i++) {
            if (dataHistoriesArray.get(i).isJsonNull()) {
                DataDTO dataDTO = new DataDTO();
                dataDTOList.add(dataDTO);
                continue;
            }

            JsonObject oneData = dataHistoriesArray.get(i).getAsJsonObject();

//            System.out.println(oneData);

            DataDTO dataDTO = new DataDTO();
            dataDTO.setDataName(oneData.get("dataName").getAsString());
            dataDTO.setStandardCode(oneData.get("standardCode").getAsString());
            dataDTO.setRemark(oneData.get("remark").getAsString());
            dataDTO.setStages(gson.fromJson(oneData.get("stages"), new TypeToken<Map<String, List<FileDTO>>>() {
            }.getType()));


            dataDTOList.add(dataDTO);
        }


        return dataDTOList;
    }

    //获取当前存在的所有数据
    public List<DataDTO> queryAllDataHistory() throws Exception {


        byte[] dataHistory = contract.evaluateTransaction("queryAllData");

        String result = StringUtils.newStringUtf8(dataHistory);

        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(result, JsonObject.class);
        JsonArray dataHistoriesArray = jsonObject.getAsJsonArray("dataHistories");
        List<DataDTO> dataDTOList = new ArrayList<>();
        for (int i = 0; i < dataHistoriesArray.size(); i++) {
            JsonObject oneData = dataHistoriesArray.get(i).getAsJsonObject();
            DataDTO dataDTO = new DataDTO();
            dataDTO.setDataName(oneData.get("dataName").getAsString());
            dataDTO.setStandardCode(oneData.get("standardCode").getAsString());
            dataDTO.setRemark(oneData.get("remark").getAsString());
            dataDTO.setStages(gson.fromJson(oneData.get("stages"), new TypeToken<Map<String, List<FileDTO>>>() {
            }.getType()));
            dataDTOList.add(dataDTO);
        }
        return dataDTOList;
    }

    public DataDTO combineDataHistory(List<DataDTO> dtoList) throws Exception{
        DataDTO dataDTO = dtoList.get(0);
        Map<String,List<FileDTO>> stages=dataDTO.getStages();
        for(DataDTO dto : dtoList)
            dto.getDataName();
        return dataDTO;
    }
}
